﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AssetManagementSystem.Utils;
using AssetManagementSystem.Model.IDao;

namespace AssetManagementSystem.Model {
    public class LoanManager {

       ILoanDAO dao;

       public LoanManager() {
            //get the loan dao
            dao = DAOManager.GetLoanDAO();
        }

        //====================================================================
        //  STANDARD CRUD METHODS
        //====================================================================

        public void CreateLoan(Loan loan) {
            dao.CreateLoan(loan);
        }

        public List<Loan> GetAllLoans() {
            return dao.GetAllLoans().ToList<Loan>();
        }

        public Loan GetLoan(int id) {
            return dao.GetLoan(id);
        }

        public void UpdateLoan(Loan loan) {
            dao.UpdateLoan(loan);
        }

        public void DeleteLoan(Loan loan) {
            dao.DeleteLoan(loan);
        }

        public void DeleteLoanAssets(int loanId, Dictionary<string, DateTime> assets) {
            //delete every asset found in dictionary
            foreach (KeyValuePair<string, DateTime> asset in assets) {
                dao.DeleteLoanAsset(loanId, asset.Key);
            }
        }

        public void ReturnLoan(Loan loan) {
            //return all loan items that haven't already been returned
            List<string> keyList = new List<string>();
            //find all assets that's arn't returned
            foreach (KeyValuePair<string, DateTime> asset in loan.Assets) {
                if (asset.Value == DateTime.MinValue) {
                    keyList.Add(asset.Key);
                }
            }
            //return the assets now.
            foreach (string key in keyList) {
                loan.Assets[key] = DateTime.Now;
            }

            dao.UpdateLoan(loan);
        }

        public void ReturnLoanAsset(Loan loan, string assetId) {
            //if the loan contains the asset, set its return date and update the loan
            if (loan.Assets.ContainsKey(assetId)) {
                loan.Assets[assetId] = DateTime.Now;
                dao.UpdateLoan(loan);
            }
        }

        //====================================================================
        //  END - STANDARD CRUD METHODS
        //====================================================================

        //====================================================================
        //  ENHANCED METHODS
        //====================================================================

        /// <summary>
        /// Attempts to find loans contain part, or all of the input text in their string representations (ToString()).
        /// The results are sorted by relevance.
        /// </summary>
        /// <param name="input">The text to search for</param>
        /// <returns>The list of sorted results</returns>
        public List<Loan> FindLoans(string input) {
            //Get all loans
            List<Loan> allLoans = GetAllLoans();
            //Create a list to store results
            List<SortObject> sortList = new List<SortObject>();
            //Get all loans with at least one tri-gram match to the input
            foreach (Loan loan in allLoans) {
                int ngramMatches = SearchUtil.NGramSearch(input, loan.ToString(), 3);
                if(ngramMatches > 0){
                    sortList.Add(new SortObject(ngramMatches, loan));
                }
            }
            //Sort the results by the number of matches they each had
            sortList.Sort();
            //Turn the results back into a list of loans
            List<Loan> matchedLoans = new List<Loan>();
            foreach (SortObject obj in sortList) {
                matchedLoans.Add((Loan)obj.TheObject);
            }
            //return the sorted results
            return matchedLoans;
        }

        public bool isLoanAssetAvailable(string assetId) {
            return dao.IsLoanAssetAvailable(assetId);
        }

        //====================================================================
        //  END - ENHANCED METHODS
        //====================================================================
    }
}
